/******************************************************************************
 * This file is part of ZSTRING.
 *
 * ZSTRING is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * ZSTRING is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with ZEMB.  If not, see <http://www.gnu.org/licenses/>.
 *
 * Project: zstring
 * Author : FergusZeng
 * Email  : cblock@126.com
 * git	  : https://gitee.com/newgolo/zstring.git
 * Copyright 2022~2025 @ ShenZhen ,China
*******************************************************************************/
#ifndef __ZSTRING_H__
#define __ZSTRING_H__

#ifdef __cplusplus
extern "C" {
#endif

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

extern unsigned char z_debug_enable;
void zdebug_set(int debug);
#ifndef PRINT
#define PRINT(fmt,...)          do{printf(fmt,##__VA_ARGS__);}while(0)
#endif
#ifndef PRINT_RED
#define PRINT_RED(fmt,...)      do{printf("\033[31m\033[1m" fmt "\033[0m\n",##__VA_ARGS__);}while(0)
#endif
#ifndef PRINT_GREEN
#define PRINT_GREEN(fmt,...)    do{printf("\033[32m\033[1m" fmt "\033[0m\n",##__VA_ARGS__);}while(0)
#endif
#ifndef PRINT_YELLOW
#define PRINT_YELLOW(fmt,...)   do{printf("\033[33m\033[1m" fmt "\033[0m\n",##__VA_ARGS__);}while(0)
#endif
#ifndef PRINT_PINK
#define PRINT_PINK(fmt,...)     do{printf("\033[35m\033[1m" fmt "\033[0m\n",##__VA_ARGS__);}while(0)
#endif
#ifndef PRINT_CYAN
#define PRINT_CYAN(fmt,...)     do{printf("\033[36m\033[1m" fmt "\033[0m\n",##__VA_ARGS__);}while(0)
#endif
#ifndef PRINT_WARN
#define PRINT_WARN(fmt,...)     {PRINT_YELLOW("%s,L%d:" fmt,__FUNCTION__,__LINE__,##__VA_ARGS__);}
#endif
#ifndef PRINT_ERR
#define PRINT_ERR(fmt,...)      {PRINT_RED("%s,L%d:" fmt,__FUNCTION__,__LINE__,##__VA_ARGS__);}
#endif
#ifndef PRINT_DBG
#define PRINT_DBG(fmt,...)      {if(z_debug_enable){PRINT_GREEN("%s,L%d:" fmt,__FUNCTION__,__LINE__,##__VA_ARGS__);}}
#endif


/* 为便于嵌入式平台移植,以下常用函数使用宏替代 */
#define EXIT(errcode)           exit(errcode)
#define FREE(...)               free(__VA_ARGS__)
#define FREE_SAFE(ptr)          do{if (ptr) {free(ptr); ptr = NULL;}}while(0)
#define MALLOC(...)             malloc(__VA_ARGS__)
#define MEMCHR(...)             memchr(__VA_ARGS__)
#define MEMCMP(...)             memcmp(__VA_ARGS__)
#define MEMCPY(...)             memcpy(__VA_ARGS__)
#define MEMMOVE(...)            memmove(__VA_ARGS__)
#define MEMSET(...)             memset(__VA_ARGS__)
#define REALLOC(...)            realloc(__VA_ARGS__)

typedef struct ZString {
    void* thiz;
} ZString;
extern const int ZString_npos;

/**
 * @brief create ZString
 * @return ZString* return a new ZString object, remember destroy it!
 */
ZString* ZString_create();

/**
 * @brief create ZString from string
 * @param str
 * @return ZString* return a new ZString object, remember destroy it!
 */
ZString* ZString_createWithStr(const char* str);

/**
 * @brief create ZString from byte array
 * @param data
 * @param size
 * @return ZString* return a new ZString object, remember destroy it!
 */
ZString* ZString_createWithData(const char* data, int size);

/**
 * @brief clone a ZString
 * @param thiz
 * @return ZString* return a new ZString object, remember destroy it!
 */
ZString* ZString_clone(ZString* thiz);

/**
 * @brief destroy ZString
 * @param thiz
 */
void ZString_destroy(ZString* thiz);

/**
 * @brief get ZString data
 * @param thiz
 * @return char*
 */
char* ZString_data(ZString* thiz);

/**
 * @brief get ZString length
 * @param thiz
 * @return int
 */
int ZString_size(ZString* thiz);

/**
 * @brief get char at position pos
 * @param thiz
 * @param pos 
 * @return char 
 */
char ZString_at(ZString* thiz, int pos);

/**
 * @brief clear ZString
 * @param thiz
 */
void ZString_clear(ZString* thiz);

/**
 * @brief find str position in ZString from a begin pos
 * @param thiz 
 * @param pos 
 * @param findStr
 * @param size 
 * @return int 
 */
int ZString_find(ZString* thiz, int pos, const char* findStr, int size);

/**
 * @brief append a ZString to the end of ZString
 * @param thiz
 * @param object
 */
void ZString_append(ZString* thiz, const ZString* object);

/**
 * @brief append a char to the end of ZString
 * @param thiz
 * @param ch
 */
void ZString_appendCh(ZString* thiz, char ch);

/**
 * @brief append a str to the end of ZString
 * @param thiz
 * @param str
 */
void ZString_appendStr(ZString* thiz,const char* str);

/**
 * @brief append byte array to the end of ZString
 * @param thiz
 * @param data
 * @param size
 */
void ZString_appendData(ZString* thiz,const char* data, int size);

/**
 * @brief erase ZString from the position pos
 * @param thiz
 * @param pos
 * @param count
 * @return int return the position of the char following the erased char
 */
int ZString_erase(ZString* thiz, int pos, int count);

/**
 * @brief insert a char before the position pos
 * @param thiz
 * @param pos
 * @param ch
 * @return int return the position of the char inserted
 */
int ZString_insert(ZString* thiz, int pos, char ch);

/**
 * @brief insert byte array at the position pos
 * @param thiz
 * @param pos
 * @param data
 * @param len
 */
void ZString_insertData(ZString* thiz, int pos, const char* data, int len);

/**
 * @brief insert a ZString at the position pos
 * @param thiz
 * @param object
 */
void ZString_insertString(ZString* thiz, int pos, const ZString* object);

void ZString_hexViewer(ZString* thiz, char* tag);

#ifdef __cplusplus
}
#endif
#endif